package edu.umd.ion.wavemeter.client;

import com.google.gwt.xml.client.Document;
import com.google.gwt.xml.client.XMLParser;
import com.google.gwt.xml.client.NodeList;
import com.google.gwt.xml.client.Element;
import com.google.gwt.xml.client.impl.DOMParseException;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.FlexTable;
import com.google.gwt.user.client.ui.Panel;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.HasHorizontalAlignment;
import com.google.gwt.user.client.ui.HasVerticalAlignment;
import com.google.gwt.user.client.ResponseTextHandler;

import edu.umd.ion.wavemeter.service.WavemeterData;
import edu.umd.ion.wavemeter.service.WavemeterDataMask;
import edu.umd.ion.wavemeter.service.WavemeterServiceAsync;

import java.lang.Integer;
import java.util.Vector;

/**
 * Widget class implementing the Wavelength Result tab of the client application.
 */
public class WavemeterWidget extends Composite implements ResponseTextHandler, NeedsDataPoll {
	private FlexTable MyTable;
	private Label TemperatureLabel;
	private HTML[] MessageLabels;
	private HTML ErrorMessage;
	private Vector<WavemeterChannelWidgetBase> MyChannelWidgets = new Vector<WavemeterChannelWidgetBase>();
	private Vector<WavemeterWidgetInterface> MyWidgets = new Vector<WavemeterWidgetInterface>();
	private int Columns = 2;
	private Document SettingsDoc; 
	private Settings MySettings;
	private VerticalPanel vert;
	private WavemeterServiceAsync WavemeterService;
	private Panel ErrorPanel;
	private StyleSheetManager styleSheetManager;

	public Settings getSettings()	{
		return MySettings;
	}
	
	public void set(WavemeterData data, WavemeterDataMask NewRequestMask ) {
		if (MessageLabels != null) {
			for (int c = 0; c < MyChannelWidgets.size(); ++c) {
				MyChannelWidgets.get(c).set(
						data.ChannelData[MyChannelWidgets.get(c).getChannelNumber()]);
			}
			for (int i=0; i<MyWidgets.size(); ++i) {
				((WavemeterWidgetInterface) MyWidgets.get(i)).set(data, NewRequestMask);
			}
			TemperatureLabel.setText(String.valueOf(data.Temperature) + " C");
		}
	}
	
	public void setMessage(int index, String message) {
		if (MessageLabels!=null)
			MessageLabels[index].setHTML(message);
	}
	
	private AsyncCallback<Integer> ChannelNumberCallback = new AsyncCallback<Integer>() {
		@Override
		public void onFailure(Throwable caught) {			
		}
		@Override
		public void onSuccess(Integer result) {
			Initialize(result);
		}
	};
	
	public void Initialize() {
		WavemeterService.getNumberOfChannels(ChannelNumberCallback);
	}
	
	public void Initialize(int NumChannels)
	{
//		try {
			int MaxColumn = 0;
			int MaxRow = 0;
			FlexTable.FlexCellFormatter Formatter = MyTable.getFlexCellFormatter();

			NodeList OptionsList = SettingsDoc.getElementsByTagName("Options");
			for (int c = 0; c < OptionsList.getLength(); ++c )
			{
				com.google.gwt.xml.client.Element ThisNode = (Element) OptionsList.item(c);
				if (ThisNode.hasAttribute("InactiveColor")) WavemeterChannelWidgetBase.inactiveColor = ThisNode.getAttribute("InactiveColor");
				if (ThisNode.hasAttribute("ActiveColor")) WavemeterChannelWidgetBase.activeColor = ThisNode.getAttribute("ActiveColor");
				if (ThisNode.hasAttribute("InRangeColor")) WavemeterChannelWidgetBase.inRangeColor = ThisNode.getAttribute("InRangeColor");
				if (ThisNode.hasAttribute("OutOfRangeColor")) WavemeterChannelWidgetBase.outOfRangeColor = ThisNode.getAttribute("OutOfRangeColor");
				if (ThisNode.hasAttribute("LockedBackgroundColor")) WavemeterChannelWidgetBase.lockedBackgroundColor = ThisNode.getAttribute("LockedBackgroundColor");
				if (ThisNode.hasAttribute("BackgroundColor")) WavemeterChannelWidgetBase.backgroundColor = ThisNode.getAttribute("BackgroundColor");
				if (ThisNode.hasAttribute("OutOfLockBackgroundColor")) WavemeterChannelWidgetBase.outOfLockBackgroundColor = ThisNode.getAttribute("OutOfLockBackgroundColor");
				if (ThisNode.hasAttribute("OutOfLockDeviation")) WavemeterChannelWidgetBase.OutOfLockDeviation = Double.parseDouble(ThisNode.getAttribute("OutOfLockDeviation"));
				if (ThisNode.hasAttribute("Theme")) styleSheetManager.updateStyleSheets(ThisNode.getAttribute("Theme"));
			}
			
			NodeList ChannelList = SettingsDoc.getElementsByTagName("Channel");
			Vector<WavemeterChannelWidgetBase> MyTmpChannelWidgets = new Vector<WavemeterChannelWidgetBase>();
			for (int c = 0; c < ChannelList.getLength(); ++c )
			{
				com.google.gwt.xml.client.Element ThisNode = (Element) ChannelList.item(c);
				int index = Integer.parseInt(ThisNode.getAttribute("index"));
				boolean showunit = ThisNode.hasAttribute("showunit")?
						Integer.parseInt(ThisNode.getAttribute("showunit"))==1:true;
				WavemeterChannelWidgetBase Current;
				if (String.valueOf("simple").equals(ThisNode.getAttribute("type"))) {
					Current = new WavemeterSimpleChannelWidget(WavemeterService, index, showunit, ErrorPanel );
					Current.initialize(ThisNode);
				} else if (String.valueOf("timechart").equals(ThisNode.getAttribute("type"))){
					WavemeterTimechartWidget TCW = new WavemeterTimechartWidget(WavemeterService, index, showunit, ErrorPanel);
					TCW.initialize(ThisNode);
					Current = TCW;
				} else {
					String Name = ThisNode.hasAttribute("name")?ThisNode.getAttribute("name"):"Channel "+index;
					WavemeterChannelWidget WCW = new WavemeterChannelWidget(WavemeterService, index, Name, showunit,ErrorPanel  );
					WCW.initialize(ThisNode);
					Current = WCW;
				}
				if (ThisNode.hasAttribute("unit"))
				{
					Current.setUnit(Integer.parseInt(ThisNode.getAttribute("unit")));
				}			
				Current.setTableProp( Integer.parseInt(ThisNode.getAttribute("row")),
								Integer.parseInt(ThisNode.getAttribute("column")),
								ThisNode.hasAttribute("colspan")?Integer.parseInt(ThisNode.getAttribute("colspan")):1 );
				MyTmpChannelWidgets.add(Current);
				Current.setWavelengthLabelHeight(ThisNode.getAttribute("size"));
				MaxColumn = Math.max(MaxColumn, Current.getColumn());
				MaxRow = Math.max(MaxRow, Current.getRow());
			}
			
			while (MyTable.getRowCount()>0) {
				MyTable.removeRow(0);
			}
			for (int c=0; c<MyTmpChannelWidgets.size(); ++c )
			{
				WavemeterChannelWidgetBase Current = MyTmpChannelWidgets.get(c);
				int row = Current.getRow();
				int column = Current.getColumn();
				int colspan = Current.getColumnSpan();
				Formatter.setColSpan(row, column, colspan );
				//GWT.log(" MyTable "+row+" "+column+" "+Current.getClass().getName(),null);
				MyTable.setWidget(row,column,Current);
				MyTable.getCellFormatter().setAlignment(row, column, HasHorizontalAlignment.ALIGN_LEFT,
						HasVerticalAlignment.ALIGN_TOP);
			}
			
			NodeList WidgetList = SettingsDoc.getElementsByTagName("Widget");
			Vector<WavemeterWidgetInterface> MyTmpWidgets = new Vector<WavemeterWidgetInterface>();
			for (int i=0; i<WidgetList.getLength(); ++i)
			{
				WavemeterWidgetInterface Current;
				Element ThisNode = (Element) WidgetList.item(i);
				Current = new WavemeterPatternWidget(NumChannels);
				Current.initialize(ThisNode);
				MyTmpWidgets.add(Current);
				int row  = Integer.parseInt(ThisNode.getAttribute("row"));
				int column  = Integer.parseInt(ThisNode.getAttribute("column"));
				if (ThisNode.hasAttribute("colspan"))
				{
					Formatter.setColSpan(row, column, 
							Integer.parseInt(ThisNode.getAttribute("colspan")));
				}
				MaxColumn = Math.max(MaxColumn, column);
				MaxRow = Math.max(MaxRow, row);
				MyTable.setWidget(row, column, Current.getWidget() );
				MyTable.getCellFormatter().setAlignment(row, column, HasHorizontalAlignment.ALIGN_LEFT,
						HasVerticalAlignment.ALIGN_TOP);
			}

			for (int c=0; c<Columns; ++c) {
				MyTable.getColumnFormatter().setWidth(c, (100/(MaxColumn+1))+"%");
			}
			
			MyChannelWidgets = MyTmpChannelWidgets;
			MyWidgets = MyTmpWidgets;
//		}
//		catch(Exception ex)
//		{
//			ErrorLabel.setHTML(ex.getMessage());
//		}
	}
	
	public WavemeterWidget(WavemeterServiceAsync service, Panel errorPanel, StyleSheetManager styleSheetMan ) {
		ErrorPanel = errorPanel;
		WavemeterService = service;
	    MyTable = new FlexTable();
	    MyTable.setStyleName("layout-WavemeterWidget");
	    styleSheetManager = styleSheetMan;
	    vert = new VerticalPanel();
	    TemperatureLabel = new Label();
	    MessageLabels = new HTML[2];
	    MessageLabels[0] = new HTML();
	    MessageLabels[1] = new HTML();
	    ErrorMessage = new HTML();
	    ErrorPanel.add(ErrorMessage);
	    
	    vert.add(MyTable);
	    vert.add(TemperatureLabel);
	    vert.add(MessageLabels[0]);
	    vert.add(MessageLabels[1]);
	    vert.setWidth("100%");
	    initWidget(vert);
	}
	
	public void onCompletion(String response) {
		try {
			SettingsDoc = XMLParser.parse(response);
			ErrorMessage.setText("");
		} 
		catch (DOMParseException ex) {
			ErrorMessage.setText(ex.getMessage());
		}
		Initialize();
	}
}
	
